using System;
using System.Collections.Generic;
using System.Text;
using Crm.Domain.TestUtil;
using Crm.Domain.TestUtil.ObjectMothers;
using NUnit.Framework;
using Crm.Domain.TestUtil.ObjectMothers;

namespace Crm.Domain.Tests
{
    [TestFixture]
    public class AddressLineTests
    {
        #region Tests - Address Lines

        [Test]
        public void CanCreateWithMultipleAddressLines()
        {
            Address address = CreateAddress(AddressCommonTestValues.AddressLines);

            int addressIndex = 0;

            foreach (string addressLine in AddressCommonTestValues.AddressLines)
            {
                Assert.AreEqual(AddressCommonTestValues.AddressLines[addressIndex], addressLine, "Address line was not correct.");

                addressIndex++;
            }
        }

        [Test]
        public void NotAffectedByChangesToAddressLines()
        {
            const string NewAddressLine = "MODIFIED";
            const int AddressLineIndex = 0;

            string[] modifiableAddressLines = GetCopyOfArray(AddressCommonTestValues.AddressLines);

            Address address = CreateAddress(modifiableAddressLines);

            modifiableAddressLines[AddressLineIndex] = NewAddressLine;

            string addressLine = GetAddressLineByIndex(address, AddressLineIndex);

            Assert.AreNotEqual(NewAddressLine, addressLine);
        }

        [Test]
        [ExpectedException(typeof(ArgumentNullException))]
        public void AddressLinesCannotBeNull()
        {
            CreateAddress(null);
        }

        [Test]
        [ExpectedException(typeof(ArgumentException))]
        public void AddressLinesCannotBeEmpty()
        {
            CreateAddress(new string[] { } );
        }

        /// <summary>
        /// We could just ignore empty address lines but for now the class will raise an exception.
        /// </summary>
        [Test]
        [ExpectedException(typeof(ArgumentException))]
        public void NoAddressLineCanBeEmptyString()
        {
            string[] WithEmptyAddressLine = { "First", "Second", String.Empty, "Fourth" };

            CreateAddress(WithEmptyAddressLine);
        }

        [Test]
        [ExpectedException(typeof(ArgumentException))]
        public void NoAddressLineCanBeNull()
        {
            string[] WithEmptyAddressLine = { "First", "Second", null };

            CreateAddress(WithEmptyAddressLine);
        }

        #endregion

        #region Support Methods

        private Address CreateAddress(string[] addressLines)
        {
            return AddressObjectMother.CreateWithAddressLines(addressLines);
        }

        private static string[] GetCopyOfArray(string[] toCopy)
        {
            string[] modifiableAddressLines = new string[toCopy.Length];
            toCopy.CopyTo(modifiableAddressLines, 0);
            return modifiableAddressLines;
        }

        private string GetAddressLineByIndex(Address address, int index)
        {
            // NOTE: This sort of method makes me think using IEnumerable for the address lines was a bad idea, maybe rethink.

            int count = 0;

            foreach (string addressLine in address.AddressLines)
            {
                if (count == index)
                {
                    return addressLine;
                }
            }

            throw new ArgumentException("Could not find address line by index.");
        }

        #endregion
    }
}
